package com.example.videopractice.audiotrack

import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioTrack
import android.os.Bundle
import android.os.Environment
import com.example.base.base.BaseBindingActivity
import com.example.base.util.ALog
import com.example.videopractice.databinding.ActivityAudioTrackBinding
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.DataInputStream
import java.io.File
import java.lang.Exception

/**
 *  AudioTrack 使用与详解 DEMO
 */
class AudioTrackActivity : BaseBindingActivity<ActivityAudioTrackBinding>() {

    private var audioTrack: AudioTrack? = null
    private var audioData: ByteArray? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding.btnRead.setOnClickListener {
            readAudioData()
        }
        binding.btnPlayStatic.setOnClickListener {
            playAudioByStatic()
        }
        binding.btnPlaySteam.setOnClickListener {
            playAudioBySteam()
        }
    }

    override fun onPause() {
        super.onPause()
        releaseAudioTrack()
    }

    private fun readAudioData() {
        GlobalScope.launch(IO) {
            runCatching {
                // 使用上一节录制生成的音频
                val path =
                    Environment.getExternalStorageDirectory().absolutePath + File.separator + "test1.wav"
                val audioFile = File(path)
                val fileSize = audioFile.length()
                ALog.e("xiao", "fileSize: $fileSize")
                val inputStream = audioFile.inputStream()
                val outputStream = ByteArrayOutputStream(fileSize.toInt())
                inputStream.use { input ->
                    outputStream.use { output ->
                        var data: Int
                        while (input.read().also { data = it } != -1) {
                            output.write(data)
                        }
                        ALog.e("xiao", "Got the data")
                        audioData = output.toByteArray()
                    }
                }
            }.onSuccess {
                ALog.e("xiao", "读取音频文件成功")
                withContext(Main) {
                    binding.btnPlayStatic.isEnabled = true
                    binding.btnPlaySteam.isEnabled = true
                }
            }.onFailure {
                ALog.e("xiao readAudioData error", it.message)
                it.printStackTrace()
            }

        }
    }

    private fun playAudioByStatic() {
        binding.btnPlayStatic.isEnabled = false
        GlobalScope.launch(IO) {
            runCatching {
                releaseAudioTrack()
                audioTrack = AudioTrack(
                    AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO,
                    AudioFormat.ENCODING_PCM_16BIT, audioData!!.size, AudioTrack.MODE_STATIC
                )
                ALog.e("xiao", "Writing audio data...")
                audioTrack?.write(audioData!!, 0, audioData!!.size)
                ALog.e("xiao", "Starting playback")
                audioTrack?.play()
                ALog.e("xiao", "Playing")
            }.onSuccess {
                withContext(Main) {
                    binding.btnPlayStatic.isEnabled = true
                }
            }.onFailure {
                ALog.e("xiao playAudio error", it.message)
                it.printStackTrace()
            }
        }
    }

    private fun playAudioBySteam() {
        releaseAudioTrack()
        GlobalScope.launch(IO) {
            try {
                // 使用上一节录制生成的音频
                val path =
                    Environment.getExternalStorageDirectory().absolutePath + File.separator + "test1.wav"
                val audioFile = File(path)
                val bufferSize = AudioTrack.getMinBufferSize(
                    44100,
                    AudioFormat.CHANNEL_OUT_STEREO,
                    AudioFormat.ENCODING_PCM_16BIT
                )
                audioTrack = AudioTrack(
                    AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO,
                    AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM
                )
                val buffer = ByteArray(bufferSize)
                val inputStream = DataInputStream(audioFile.inputStream())
                inputStream.use { input ->
                    var readCount = 0
                    while (input.available() > 0) {
                        readCount = input.read(buffer)
                        if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {
                            continue
                        }
                        if (readCount != 0 && readCount != -1) {
                            audioTrack?.play()
                            audioTrack?.write(buffer, 0, readCount)
                        }
                    }
                }
            } catch (e: Exception) {
                ALog.e("xiao playAudio error", e.message)
                e.printStackTrace()
            }
        }
    }

    private fun releaseAudioTrack() {
        audioTrack?.stop()
        audioTrack?.release()
    }

}